home *** CD-ROM | disk | FTP | other *** search
- /* PRINT.C
- ************************************************************************
- * *
- * PC Scheme/Geneva 4.00 Borland C code *
- * *
- * (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- * (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- * *
- *----------------------------------------------------------------------*
- * *
- * Print an Atom *
- * *
- *----------------------------------------------------------------------*
- * *
- * Created by: John Jensen Date: 1985 *
- * Revision history: *
- * - 2 Oct 87: modified PRINT-ATOM to recognize special atoms such as *
- * #T, #F, etc. (tc) *
- * - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- * *
- * ``In nomine omnipotentii dei'' *
- ************************************************************************/
-
- #include <stdarg.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "scheme.h"
-
- /************************************************************************/
- /* Main Print Driver - zprintf */
- /* */
- /************************************************************************/
- void zprintf(char *fmt, ...)
- {
- char buf[2000], *p;
- va_list argptr;
-
- va_start(argptr, fmt);
- vsprintf(buf, fmt, argptr);
- va_end(argptr);
-
- /* set the default port address for the I/O operation */
- ssetadr(ADJPAGE(OUT_PAGE), OUT_DISP);
-
- for( p = buf; *p; outchar(*p++) );
- }
-
- extern char decpoint; /* The current decimal point character */
- extern int ccount;
-
- /****************************************************************/
- /* PRINTATM(pg,ds,offs,c) */
- /* PRINTATM is used for printing both symbols (and */
- /* strings). The atom to be printed is located at logical page */
- /* PG and displacement DS. The argument OFFS tells how many */
- /* bytes from the top of the atom begin the characters to be */
- /* printed. The atom printname will be bracketed with the */
- /* character CH at both ends if necessary. */
- /* ( CH=='|' for symbols, '"' for strings.) */
- /****************************************************************/
- void printatm(unsigned pg, unsigned ds, unsigned offs, char ch)
- {
- int j;
- char *buf;
- int len; /* Length of print name */
- int strange = 0; /* Number of strange characters */
-
- /* First stage: Copy pname into buffer, count needed escape */
- /* characters, and determine whether the pname is "strange". */
- len = get_word(pg, ds + 1) - offs;
- ds += offs;
- if (!(buf = (char *) malloc(offs = 2 * len + 1)))
- malloc_error("printatm");
- strange = (j = blk2pbuf(pg, ds, buf, len, ch, show & SP_OUTPUT)) & 1;
- j >>= 1;
-
- /* Second stage: If necessary, check for numeric, dot, or */
- /* #-macro confusion. */
- if (!strange)
- if ((!strcmp(buf, ".")) || (*buf == '#') && (pg != SPECSYM) || (scannum(buf, 10)))
- strange++;
-
- /* Third stage: Send carriage-return if needed, and print */
- /* pname of atom, delimited if necessary. */
- stage_3:
- ccount += len; /* Update character count */
- if (show & SP_SEPARE) {
- wrap(j + (((strange = (strange && (show & SP_OUTPUT))) != 0) ? 2 : 0));
- if (strange)
- givechar(ch);
- gvchars(buf, j);
- if (strange)
- givechar(ch);
- }
- free(buf);
- }
-
- /****************************************************************/
- /* PRINTFLO(f) */
- /* Given a double-length floating-point number, this */
- /* procedure formats and prints the ASCII representation of */
- /* the number. */
- /****************************************************************/
- void printflo(double f)
- {
- char buf[32];
- printstr(buf, makeflo(f, (BIGDATA *) buf, 0, outrange(f)));
- }
-
- /****************************************************************/
- /* OUTRANGE(f) */
- /* Returns a non-zero value if the value of the given */
- /* flonum F is not "close" to 1, zero otherwise. */
- /****************************************************************/
- int outrange(double f)
- {
- if (f < 0)
- f = -f;
- return (f < 1.0e-3) || (f >= 1.0e7);
- }
-
- /****************************************************************/
- /* MAKEFLO(flo,buf,prec,ex) */
- /* Takes a flonum FLO and converts it to a human-readable */
- /* form, storing the characters in the buffer BUF. PREC */
- /* specifies the number of decimal places to be used (as many */
- /* as necessary, up to a maximum, if PREC is 0) and EX */
- /* specifies whether to use exponential (if nonzero) or fixed- */
- /* decimal format. MAKEFLO returns the number of characters */
- /* placed in BUF, and BUF should be at least 32 bytes. */
- /****************************************************************/
- int makeflo(double flo, BIGDATA *buf, int prec, int ex)
- {
- char digits[32];
- int scl = 0;
- if (flo == 0.0) {
- *digits = '0';
- ex = 0;
- } else {
- scale(&flo, &scl);
- flo2big(flo * 1.0e15, buf);
- big2asc(buf, digits);
- }
- return formflo(digits, buf, scl, prec, ex);
- }
-
- /****************************************************************/
- /* SCALE(&flo,&x) */
- /* Given a pointer FLO to a double-length flonum and a */
- /* pointer X to an integer, SCALE puts at those two locations */
- /* a new flonum and integer such that FLO equals the new */
- /* flonum times 10 to the integer's power and the new flonum */
- /* is in the interval [ 1.0, 10.0 ). */
- /****************************************************************/
- void scale(double *flo, int *x)
- {
- double local;
- double squar = 10.0;
- double tensquar[9];
- int scale, wassmall, i;
-
- scale = wassmall = i = 0;
- local = ((*flo > 0) ? *flo : -*flo);
- if (local == 0)
- *x = 0;
- else {
- if (local < 1.0) {
- wassmall = -1;
- local = 1.0 / local;
- }
- tensquar[0] = 10.0;
- while (++i < 9) {
- squar *= squar;
- tensquar[i] = squar;
- }
- while (--i >= 0) {
- scale <<= 1;
- if (local >= tensquar[i]) {
- local /= tensquar[i];
- scale++;
- }
- }
- if (wassmall) {
- scale = -scale;
- local = 1.0 / local;
- if (local != 1.0) {
- local *= 10;
- scale--;
- }
- }
- *x = scale;
- *flo = ((*flo < 0.0) ? -local : local);
- }
- }